package diagnostic

import "mi/compiler/ast"

type RecoveryPoint struct {
	length int
	valid bool
	kind string
}

const ParseDiagnostics = "ParseDiagnostics"
const BindDiagnostics  = "BindDiagnostics"
const SyntacticErrors = "SyntacticErrors"

func assert(expr bool) {
	if !expr {
		panic("Assert Fail")
	}
}

func GetSourceFileDiagnostics(file ast.Node, kind string) []*Diagnostic {
	assert(ast.IsSourceFile(file) || ast.IsProjectFile(file))
	if file.Get(kind) != nil {
		return file.Get(kind).([]*Diagnostic)
	}
	return nil
}

func SetDiagnosticToSourceFile(file ast.Node, kind string, diagnostics []*Diagnostic) {
	assert(ast.IsSourceFile(file) || ast.IsProjectFile(file))
	file.Set(kind, diagnostics)
}

func AddDiagnosticToSourceFile(file ast.Node, kind string, msg *Diagnostic) {
	assert(ast.IsSourceFile(file) || ast.IsProjectFile(file))
	var diagnostics = GetSourceFileDiagnostics(file, kind)
	diagnostics = append(diagnostics, msg)
	file.Set(kind, diagnostics)
}

func CreateSourceFileRecoveryPoint(file ast.Node, kind string) RecoveryPoint {
	assert(ast.IsSourceFile(file) || ast.IsProjectFile(file))
	var diagnostics = GetSourceFileDiagnostics(file, kind)
	return RecoveryPoint{
		length: len(diagnostics),
		valid:  true,
		kind: kind,
	}
}

func RecoverySourceFileDiagnostics(file ast.Node, point RecoveryPoint) {
	assert(ast.IsSourceFile(file) || ast.IsProjectFile(file))
	if !point.valid {
		return
	}

	var diagnostics = GetSourceFileDiagnostics(file, point.kind)
	if len(diagnostics) > point.length {
		diagnostics = diagnostics[:point.length]
	}
	file.Set(point.kind, diagnostics)
}
